package com.jacky.webflux.jwt.controller;

import com.jacky.webflux.jwt.common.BasicResp;
import com.jacky.webflux.jwt.models.UserModel;
import com.jacky.webflux.jwt.service.UserDetailsService;
import com.jacky.webflux.jwt.service.UserService;
import com.jacky.webflux.jwt.token.JwtTokenComponent;
import com.jacky.webflux.jwt.token.Role;
import com.jacky.webflux.jwt.token.TokenUser;
import com.jacky.webflux.jwt.vo.LoginVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@RestController
@RequestMapping("auth")
public class AuthController {

    private static final Logger LOGGER = LoggerFactory.getLogger(AuthController.class);
    private final UserDetailsService userDetailsService;
    private final UserService userService;
    private final JwtTokenComponent tokenComponent;
    private final PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    public AuthController(UserDetailsService userDetailsService, JwtTokenComponent jwtTokenComponent,
                          UserService userService) {
        this.userDetailsService = userDetailsService;
        this.tokenComponent = jwtTokenComponent;
        this.userService = userService;
    }

    @PostMapping(value = "login", produces = "application/json")
    public Mono<BasicResp<String>> login(@RequestBody LoginVO vo) {
        if (Objects.isNull(vo) || StringUtils.isBlank(vo.getUsername()) || StringUtils.isBlank(vo.getPassword())) {
            return Mono.just(BasicResp.fail("用户名或密码不能为空"));
        }
        return Mono.just(vo.getUsername())
                .flatMap(userDetailsService::findByUsername)
                .doOnNext(i -> LOGGER.info("{}", i))
                .filter(ud -> passwordEncoder.matches(vo.getPassword(), ud.getPassword()))
                .map(ud -> {
                    TokenUser tu = new TokenUser(ud.getUsername(), ud.getPassword(), ud.isEnabled(),
                            ud.getAuthorities().stream().map(GrantedAuthority::getAuthority).map(Role::valueOf).collect(Collectors.toList()));
                    String token = tokenComponent.generateToken(tu);
                    return BasicResp.success(token);
                })
                .onErrorResume(e -> Mono.empty())
                .switchIfEmpty(Mono.just(BasicResp.fail("登录失败")));
    }

    @PostMapping(value = "registry", produces = "application/json")
    public Mono<BasicResp<String>> registry(@RequestBody LoginVO vo) {
        if (Objects.isNull(vo) || StringUtils.isBlank(vo.getUsername()) || StringUtils.isBlank(vo.getPassword())) {
            return Mono.just(BasicResp.fail("用户名或密码不能为空"));
        }


        String encode = passwordEncoder.encode("123456");

        UserModel um = new UserModel();
        um.setUserName("Lily123");
        um.setPassword("123");
        return userService.saveUser(um)
                .map(it -> BasicResp.success("注册成功"))
                .defaultIfEmpty(BasicResp.fail("注册失败"));


        /*return userService.findByUsername(vo.getUsername())
                .map(it -> {
                    String encodePwd = passwordEncoder.encode(vo.getPassword());
                    UserModel userModel = new UserModel();
                    userModel.setUserName(vo.getUsername());
                    userModel.setPassword(encodePwd);
                    userModel.setEnabled(true);
                    userModel.setRoles(List.of(Role.ROLE_USER.name()));
                    userModel.setCreateAt(LocalDateTime.now());
                    userModel.setUpdateAt(LocalDateTime.now());
                    userService.saveUser(userModel);
                    return BasicResp.success("注册成功");
                })
                .defaultIfEmpty(BasicResp.fail("用户名[" + vo.getUsername() + "]已存在"));*/
    }

    public static void main(String[] args) {
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        String encode = passwordEncoder.encode("123456");
        System.out.println(encode);
    }
}
